"""
文件工具模块
提供文件操作相关的工具函数
"""

import os
from typing import List, Optional, Tuple


def get_file_size(file_path: str) -> int:
    """
    获取文件大小
    
    Args:
        file_path: 文件路径
        
    Returns:
        文件大小（字节）
    
    Raises:
        FileNotFoundError: 文件不存在时抛出
    """
    if not os.path.exists(file_path):
        raise FileNotFoundError(f"文件不存在: {file_path}")
        
    return os.path.getsize(file_path)


def get_files(dir_path: str, suffixes: List[str]) -> List[str]:
    """
    获取指定目录及其子目录下所有指定后缀的文件路径
    
    Args:
        dir_path: 目录路径
        suffixes: 文件后缀列表
        
    Returns:
        符合条件的文件路径列表
    
    Raises:
        FileNotFoundError: 目录不存在时抛出
    """
    if not os.path.exists(dir_path):
        raise FileNotFoundError(f"目录不存在: {dir_path}")
        
    if not os.path.isdir(dir_path):
        raise NotADirectoryError(f"路径不是目录: {dir_path}")
    
    files = []
    
    for item in os.listdir(dir_path):
        item_path = os.path.join(dir_path, item)
        
        if os.path.isdir(item_path):
            # 递归处理子目录
            files.extend(get_files(item_path, suffixes))
        else:
            # 检查文件后缀
            for suffix in suffixes:
                if item.lower().endswith(suffix.lower()):
                    files.append(item_path)
                    break
    
    return files


def ensure_directory(dir_path: str) -> None:
    """
    确保目录存在，如果不存在则创建
    
    Args:
        dir_path: 目录路径
    """
    if not os.path.exists(dir_path):
        os.makedirs(dir_path)


def split_files_into_batches(files: List[str], batch_size: int = 10) -> List[List[str]]:
    """
    将文件列表分割成批次
    
    Args:
        files: 文件路径列表
        batch_size: 每批次的文件数量
        
    Returns:
        批次列表，每个批次包含多个文件路径
    """
    return [files[i:i + batch_size] for i in range(0, len(files), batch_size)]


def truncate_filename(filename: str, max_bytes: int = 128) -> str:
    """
    截断文件名，确保其字节长度不超过指定值
    
    Args:
        filename: 原始文件名
        max_bytes: 最大字节数
        
    Returns:
        截断后的文件名
    """
    # 获取文件扩展名
    base, ext = os.path.splitext(filename)
    
    # 计算当前文件名的字节长度
    filename_bytes = filename.encode('utf-8')
    current_length = len(filename_bytes)
    
    # 如果已经符合要求，直接返回
    if current_length <= max_bytes:
        return filename
    
    # 计算需要保留的基本名称长度
    # 预留扩展名长度和"..."的长度
    ellipsis = "..."
    ext_bytes = ext.encode('utf-8')
    ellipsis_bytes = ellipsis.encode('utf-8')
    
    # 计算基本名称可用的最大字节数
    available_bytes = max_bytes - len(ext_bytes) - len(ellipsis_bytes)
    
    # 如果可用字节数太小，无法包含有意义的基本名称，则尽可能保留
    if available_bytes <= 0:
        # 尝试只保留扩展名
        if len(ext_bytes) <= max_bytes:
            return ext[1:]  # 去掉点号
        else:
            # 如果连扩展名都太长，则截断扩展名
            return ext[:max_bytes].decode('utf-8', errors='ignore')
    
    # 截断基本名称
    truncated_base = ""
    for i in range(len(base)):
        next_char = base[i:i+1]
        if len((truncated_base + next_char).encode('utf-8')) <= available_bytes:
            truncated_base += next_char
        else:
            break
    
    # 组合截断后的文件名
    return truncated_base + ellipsis + ext
